package org.community.loginsvc.controller;

import cn.dev33.satoken.config.SaSsoConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.sso.SaSsoProcessor;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.google.code.kaptcha.Producer;
import com.sun.istack.internal.NotNull;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.community.loginsvc.entites.Visitor;
import org.community.loginsvc.service.checkservice.CheckService;
import org.community.loginsvc.service.codeservice.CodeCheckService;
import org.community.loginsvc.service.detailservice.userinfo.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


/**
 * Sa-Token-SSO Server端 Controller
 */
@RestController
@RequiredArgsConstructor
@Data
//sso权限认证控制器
public class SsoServerController {


    //注入账号服务
    @NotNull
    private CheckService checkService;

    //注入验证码查询服务
    @NotNull
    private CodeCheckService codeCheckService;

    //注入验证码生成器
    @NotNull
    private Producer kaptchaProducer;

    @NotNull
    private UserInfoService userInfoService;

    @RequestMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoProcessor.instance.serverDister();
    }



    //验证码生成方法(转成二进制数据返回给前端)
    @GetMapping("/kaptchar")
    public Object getKaptchar() throws IOException {
        System.out.println("正在获取验证码");

        Producer codeImgProducer = this.getKaptchaProducer();
        CodeCheckService codeCheckService = this.getCodeCheckService();
        //生成验证码
        String imgCode = codeImgProducer.createText();
        //生成图片流
        BufferedImage bufferedImage = codeImgProducer.createImage(imgCode);
        //图片转成二进制
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage,"png",out);
        byte[] bytes = out.toByteArray();
        //图片加密
        BASE64Encoder encoder = new BASE64Encoder();
        String bufferdStringImage = encoder.encodeBuffer(bytes).trim();

        //将图片对应验证码存入redis，并返回对应的id
        String redisCode = codeCheckService.setCode(imgCode);

        //将对应的验证码Id返回给前端
        Map<String,String> map = new HashMap<>();
        map.put("codeId",redisCode);



        return SaResult.code(200).setMap(map).setData(bufferdStringImage);
    }


    @Autowired
    private void configSso(SaSsoConfig sso) {

        //未登录时返回的视图
        sso.setNotLoginView(() -> {
            System.out.println("进入未登录视图");
            return new ModelAndView("login");

        });

        // 配置：登录处理函数
        sso.setDoLoginHandle((name, pwd) -> {
            // 此处仅做模拟登录，真实环境应该查询数据进行登录
            System.out.println("进入登录处理方法");
            System.out.println("前端传回来的账号和密码："+name+","+pwd);
            String code = SaHolder.getRequest().getParam("code");
            String codeId = SaHolder.getRequest().getParam("codeId");
            int choice = Integer.parseInt(SaHolder.getRequest().getParam("choice"));
            System.out.println("前端传回来的验证码和验证码Id："+code+","+codeId);
            System.out.println("登录选择："+choice);

            if(!this.getCodeCheckService().checkCode(codeId,code)){
                return SaResult.code(400).setMsg("验证码错误");
            }
            //从数据库中查询
            Visitor visitor = new Visitor(null,name,pwd);
            int resultCode = this.getCheckService().accountSearchAndAuth(visitor);

            if( resultCode == 200){
                Visitor user = this.getCheckService().accountSearch(visitor);
                Integer userId = user.getUserId();
                String username = user.getUserName();
                System.out.println("用户ID："+userId+"，用户名："+username);
                return this.login(userId,username,choice);
//                return SaResult.ok("登录成功！").setData(StpUtil.getTokenValue());
            }

            if (resultCode == 404){
                return SaResult.code(404).setMsg("账号或密码错误");
            }
            return SaResult.error("服务器错误，请稍后重试或者联系管理员");






        });







    }

    private SaResult login(Integer userId,String username,int choice){
        SaLoginModel saLoginModel = new SaLoginModel();
        //是否记住用户
        if(choice == 0){
            saLoginModel.setIsLastingCookie(false);
            //创建会话
            StpUtil.login(userId,saLoginModel);
            System.out.println("会话过期时间："+StpUtil.getTokenTimeout());
            //用户回显信息存入会话中
            try {
                this.getUserInfoService().setUserInfo(userId);
            } catch (IOException e) {
                e.printStackTrace();
            }


            return SaResult.ok("登录成功！").setData(StpUtil.getTokenValue());
        }
        StpUtil.login(userId);
        //用户回显信息存入会话中
        try {
            this.getUserInfoService().setUserInfo(userId);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("会话过期时间："+StpUtil.getTokenTimeout());
        return SaResult.ok("登录成功！").setData(StpUtil.getTokenValue());
    }

}